package com.skivingcloud.admin.security;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils;

import static com.skivingcloud.admin.security.MyAuthenticationHandler.APPLICATION_JSON_CHARSET_UTF_8;

/**
 * @author hushouquan
 */
//@Component
public class UsernameNoPasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter{
    private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/login", "POST");
    private String usernameParameter = "username";
    private String passwordParameter = "password";
    private boolean postOnly;

    public UsernameNoPasswordAuthenticationFilter() {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
        postOnly = true;
    }
    
    public UsernameNoPasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
        postOnly = true;
    }
    
    public UsernameNoPasswordAuthenticationFilter(AuthenticationManager authenticationManager,
                                                  MyAuthenticationHandler authenticationHandler,
                                                  MyRememberMeServices rememberMeServices){
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
        setAuthenticationFailureHandler(authenticationHandler);
        setAuthenticationSuccessHandler(authenticationHandler);
        //rememberMe
        setRememberMeServices(rememberMeServices);
        //登陆使用的路径
        setFilterProcessesUrl("/sys/auth/login");
        postOnly = true;
    }
    
    private static boolean isContentTypeJson(HttpServletRequest request) {
        final String contentType = request.getContentType().replaceAll(" ", "");
        return APPLICATION_JSON_CHARSET_UTF_8.equalsIgnoreCase(contentType) || MimeTypeUtils.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType);
    }
    protected void setDetails(HttpServletRequest request, NoPasswordToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!HttpMethod.POST.name().equalsIgnoreCase(request.getMethod())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        //获取第三方登录用的票据或token
        String ticket = request.getParameter("ticket");
        String rememberMe = request.getParameter(MyRememberMeServices.REMEMBER_ME_KEY);
        //调用第三方接口获取用户信息
        String username = getUsernameFromIam(ticket);
        if (!ObjectUtils.isEmpty(rememberMe)) {
            request.setAttribute(MyRememberMeServices.REMEMBER_ME_KEY, rememberMe);
        }
        NoPasswordToken authRequest = new NoPasswordToken(username);
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }
    
    /**
     * 调用第三方接口获取用户信息
     * @param ticket 票据信息或token
     * @return 用户名
     */
    private String getUsernameFromIam(String ticket){
        //TODO
        return "用户名";
    }
    
    public void setUsernameParameter(String usernameParameter) {
        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
        this.usernameParameter = usernameParameter;
    }
    
    public void setPasswordParameter(String passwordParameter) {
        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
        this.passwordParameter = passwordParameter;
    }
    
    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }
    
    public final String getUsernameParameter() {
        return this.usernameParameter;
    }
    
    public final String getPasswordParameter() {
        return this.passwordParameter;
    }
}
